package com.goblin.security;

import com.alibaba.fastjson.JSONObject;
import com.goblin.common.response.AuthException;
import com.goblin.common.response.Code;
import com.goblin.common.response.Message;
import com.goblin.common.response.Response;
import com.goblin.model.uaa.po.Priv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;


public class SecurityFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(SecurityFilter.class);

    public SecurityFilter() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        OutputStream outputStream = response.getOutputStream();
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
        response.setHeader("Access-Control-Max-Age", 3600 * 24 + "");

        response.setContentType("text/html;charset=utf-8");

        String method = request.getMethod();
        String url = request.getRequestURI();
        url = url.substring(3); //去掉 /v1 版本号头

        if (method.equalsIgnoreCase("OPTIONS")) {
            servletRequest.getRequestDispatcher(request.getRequestURI()).forward(request, response);
            return;
        }

        //================================== 开放接口 ====================================
        if (url.equalsIgnoreCase("/uaa/user/login")) {
            servletRequest.getRequestDispatcher(request.getRequestURI()).forward(request, response);
            response.getOutputStream();
            return;
        }

        if (request.getRequestURI().contains("/websocket/topic")) {
            servletRequest.getRequestDispatcher(request.getRequestURI()).forward(request, response);
            response.getOutputStream();
            return;
        }


        try {
            //================================== 查看是否登录 =================================
            String authorization = request.getHeader("authorization");
            if (authorization == null) {
                throw new AuthException(Message.NO_USEFUL_TOKEN.value);
            }

            List info = AuthorityStore.getAuth(authorization);

            if (info == null) {
                throw new AuthException(Message.NO_USEFUL_TOKEN.value);
            }

            long currentTime = Long.parseLong(info.get(0).toString());
            if (System.currentTimeMillis() - currentTime > 2 * 60 * 60 * 1000) {
                AuthorityStore.delAuth(authorization);
                throw new AuthException(Message.TOKEN_INVALID.value);
            }

            //================================== 查看是否有权限 ===============================
            List<Priv> privs = (List<Priv>) info.get(3);
            for (Priv p : privs) {
                String m = p.getMethod();
                String u = p.getUrl();
                if (method.equalsIgnoreCase(m) && judgeUrlMatch(u, url)) {
                    servletRequest.getRequestDispatcher(request.getRequestURI()).forward(request, response);

                }
            }

            throw new AuthException(Message.UNAUTHORIZED.value);
        } catch (AuthException ex) {
            String resp = JSONObject
                    .toJSON(Response.failure(Code.AUTH_EXCEPTION, ex.getMessage()))
                    .toString();
            outputStream.write(resp.getBytes());
        } catch (Exception ex) {
            String resp = JSONObject.toJSON(Response
                    .failure(Code.SERVER_INTERNAL_ERROR, Message.SERVER_INTERNAL_ERROR))
                    .toString();
            outputStream.write(resp.getBytes());
        }

    }

    @Override
    public void destroy() {

    }

    /**
     * @desc: 创建priv时，用*替代/{}, 但是只能存在于末尾
     * @author goblin
     * @date 2021/2/20 15:39
     */
    private boolean judgeUrlMatch(String s, String uri) {

        if (s == null || uri == null) {
            return false;
        }

        char[] ignore = s.toCharArray();
        char[] url = uri.toCharArray();
        int len = ignore.length;
        int len1 = url.length;

        int min = len > len1 ? len1 : len;

        boolean result = true;
        for (int i = 0; i < min; i++) {

            if (ignore[i] == '*' || url[i] == '*') {
                return result;
            }

            result &= (ignore[i] == url[i]);
        }
        return result;
    }
}